import random
import copy
import locale
import defaultvalue
import astar
import turnsnpc
import evadeplayer
import randommove
import minisprite
import driver
import searchalg

##################################################
# receive a tanker object, give him orders
##################################################
class gameAI:
    def __init__(self):
        self.map = []
        self.way = []
        # different search way algorithms
        self.turn_al = turnsnpc.TurnsNpc()
        self.astar = astar.AStar()
        self.random_move = randommove.RandomMove()
        self.evade_player = evadeplayer.EvadePlayer()

    def default_start(self):
        """ default start, creat a map for itself """
        blocks = defaultvalue.defaultBlockNum
        self.length = defaultvalue.defaultLength
        self.height = defaultvalue.defaultHeight
        self.start_position = [0, 0]
        self.destination = [ self.length-1, self.height-1 ]
        # fill map with blank
        for i in xrange(self.length):
            input = []
            for j in xrange(self.height):
                input.append(0)
            self.map.append(input)
        # join start position and destination
        while 1:
            i = random.randint(0, self.length-1)
            j = random.randint(0, self.height-1)
            if i == self.destination[0] and j == self.destination[1] :
                pass
            elif i == self.start_position[0] and j == self.start_position[1] :
                pass
            else:
                self.playerPos= [i , j]
                break
        # join in blocks
        while blocks > 0:
            blocks -= 1
            i = random.randint(0, self.length-1)
            j = random.randint(0, self.height-1)
            if i == self.destination[0] and j == self.destination[1] :
                blocks += 1
            elif i == self.start_position[0] and j == self.start_position[1] :
                blocks += 1
            elif self.map[i][j] == 0:
                self.map[i][j] = 1                
        
    def load_date(self, map, tanker, tanker_pos, destination, player_pos):
        """ load parameters for the algothims """
        self.map = map
        self.height = len(self.map[0])
        self.length = len(self.map)
        self.tanker = tanker
        self.start_position = [tanker_pos[1], tanker_pos[0]]
        temp_destination = destination[random.randint(0, len(destination) - 1)]
        self.destination = [temp_destination[1], temp_destination[0]]
        temp_playerPos = player_pos[random.randint(0, len(player_pos) - 1)]
        self.playerPos = [temp_playerPos[1], temp_playerPos[0]]        

    def init_map(self,level):
        """ change the map into certain format """
        tempMap = copy.deepcopy(self.map)
        changedMap = []
        for i in xrange(2):
            for j in xrange(2):
                tempMap[self.start_position[0] + i][self.start_position[1] + j] = 0
                tempMap[self.destination [0] + i][self.destination[1] + j] = 0
                if level == 1:
                    tempMap[self.playerPos[0] + i][self.destination[1] + j] = 1
        # deal with the blocks around the destination
        i = self.destination[0]
        j = self.destination[1]
        if i - 1 >= 0 :
            i -= 1
        if j -2 >= 0:
            j -= 2
        elif j -1 >= 0:
            j -= 1
        for line_index in xrange(4):
            if i + line_index >= self.length: # reach the verge
                break
            for row_index in xrange(6):
                if j + row_index >= self.height :
                    break
                else:
                    tempMap[i + line_index][j + row_index] = 0                
        # judge if the tanker can move to a certain place        
        for i in xrange(self.length - 1):
            line = []
            for j in xrange(self.height - 1):
                value = tempMap[i][j] | tempMap[i][j + 1] | tempMap[i + 1][j] | tempMap[i + 1][j + 1]
                line.append(value)
            changedMap.append(line)
        self.map = copy.deepcopy(changedMap)
        self.height = len(self.map[0])
        self.length = len(self.map)

    
    def update(self, map, tanker, tankerpos, destination, playerPos, level):
        """ search for a route """
        self.load_date(map, tanker, tankerpos, destination, playerPos)
        self.init_map(level)
        self.decide(level)
        self.tanker.driver.clear(driver.PathSignal.KIND)
        # send fire orders
        if random.uniform(0, 1)> 0.6:
            self.tanker.fire()
        # send orders
        for index in xrange(len(self.way)):
            self.tanker.driver.send(driver.PathSignal(self.way[index], False))

    def decide(self, level):
        """ decide the smart levels of the tanker, and use certain algorithm """
        if level == 4:
            startPosition = self.start_position
            endPosition = self.destination
            self.search_way(self.astar, startPosition, endPosition)
        if level == 3:
            startPosition = self.start_position
            endPosition = self.playerPos
            self.search_way(self.astar, startPosition, endPosition)
        if level == 2:
            startPosition = self.start_position
            endPosition = self.destination   
            self.search_way(self.turn_al, startPosition, endPosition)
        if level == 1:
            startPosition = self.start_position
            endPosition = self.playerPos
            self.search_way(self.evade_player, startPosition, endPosition)
        if level == 0:
            startPosition = self.start_position
            endPosition = self.destination
            self.search_way(self.random_move, startPosition, endPosition)
        
    def search_way(self, search_al , start_position , end_position):
        self.way = search_al.search(self.map, start_position, end_position)

    def print_map(self):
        print 'The map is:\n'
        for i in xrange(self.length):
            for j in xrange(self.height):
                if i == self.start_position[0] and j == self.start_position[1]: # print start
                    print 'S\t'
                elif i == self.destination[0] and j == self.destination[1]: # print end
                    print 'E\t'
                elif i == self.playerPos[0] and j == self.playerPos[1]: # print player
                    print 'P\t'
                else:
                    print locale.str(self.map[i][j])+'\t'
            print '\n'

    def print_way(self):
        print 'start at:'
        print self.start_position
        print '\n'
        print 'destination is :'
        print self.destination
        print '\n'
        print 'The route is:\n'
        for index in xrange(len(self.way)):
            if self.way[index] == 0:
                print 'Up\t'
                tanker.driver.send(driver.PathSignal(self.way[index]))
            if self.way[index] == 1:
                print 'Left\t'
            if self.way[index] == 2:
                print 'Down\t'
            if self.way[index] == 3:
                print 'Right\t'
        print '\n'
